// ==============================================================================================
// RibbonTree.cs
//
// Created by: NI, 2007.03.26
// Revised by: NI, 2007.11.23
// ==============================================================================================
using System;
using System.Windows.Forms;
using RibbonExplorer.InfoPanel;
using RibbonExplorer.Properties;

namespace RibbonExplorer.Tree
{
  // ==============================================================================================
  /// <summary>
  /// This class represents the tree of Office ribbons by wrapping in a TreeView instance.
  /// </summary>
  // ==============================================================================================
  public class RibbonTree: INavigationSupport
  {
    #region Private Fields

    private TreeView _Tree;
    private ImageList _Images;
    private RibbonInfoPanel _InfoPanelHost;
    private RootTreeNode _RootNode;

    #endregion

    #region Lifecycle methods

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Creates an instance of the tree representing Office ribbons.
    /// </summary>
    /// <param name="tree">TreeView control to wrap in.</param>
    /// <param name="infoPanelHost">Host control for the info panel.</param>
    // --------------------------------------------------------------------------------------------
    public RibbonTree(TreeView tree, RibbonInfoPanel infoPanelHost)
    {
      if (tree == null) throw new ArgumentNullException("tree");
      _Tree = tree;
      _Images = new ImageList();
      _Tree.ImageList = _Images;
      SetupImages();
      _InfoPanelHost = infoPanelHost;
      _RootNode = new RootTreeNode("Office Applications");
      tree.Nodes.Add(_RootNode);
      _Tree.MouseDown += new MouseEventHandler(OnMouseDown);
      _Tree.BeforeExpand += new TreeViewCancelEventHandler(OnBeforeExpand);
      _Tree.AfterSelect += new TreeViewEventHandler(OnAfterSelect);
      _RootNode.Expand();
      _RootNode.AccessNode.Expand();
      _RootNode.ExcelNode.Expand();
      _RootNode.OutlookNode.Expand();
      _RootNode.PowerPointNode.Expand();
      _RootNode.WordNode.Expand();
    }

    #endregion

    #region Public Properties

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Gets the TreeView control wrapped in.
    /// </summary>
    // --------------------------------------------------------------------------------------------
    public TreeView Tree
    {
      get { return _Tree; }
    } 
    
    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Gets the TreeNode representing the tree root.
    /// </summary>
    // --------------------------------------------------------------------------------------------
    public TreeNode RootNode
    {
      get { return _RootNode; }
    }

    #endregion

    #region Tree event methods

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// This method is called before a tree node is expanded.
    /// </summary>
    /// <param name="sender">Object sending this event.</param>
    /// <param name="e">Event arguments.</param>
    // --------------------------------------------------------------------------------------------
    private void OnBeforeExpand(object sender, TreeViewCancelEventArgs e)
    {
      OnDemandTreeNode node = e.Node as OnDemandTreeNode;
      if (node != null)
      {
        // --- This is the only case we handle
        node.ExpandNode();
      }
    }

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// This method is called when a tree node is selected.
    /// </summary>
    /// <param name="sender">Object sending this event.</param>
    /// <param name="e">Event arguments.</param>
    // --------------------------------------------------------------------------------------------
    void OnAfterSelect(object sender, TreeViewEventArgs e)
    {
      if (_InfoPanelHost == null) return;
      IInfoPanelSupport infoPanel = e.Node as IInfoPanelSupport;
      if (infoPanel != null)
      {
        _InfoPanelHost.PanelControl = infoPanel.GetInfoPanelInstance(e.Node, this);
      }
    }

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// This method copies the name of the selected item to the clipboard.
    /// </summary>
    /// <param name="sender">Object sending this event.</param>
    /// <param name="e">Event arguments.</param>
    // --------------------------------------------------------------------------------------------
    void OnMouseDown(object sender, MouseEventArgs e)
    {
      TreeNode selNode = _Tree.GetNodeAt(e.Location);
      if (selNode != null && e.Button == MouseButtons.Right)
      {
        Clipboard.SetText(selNode.Text, TextDataFormat.Text);
      }
    }

    #endregion

    #region Private methods

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Initializes the images used by the application.
    /// </summary>
    // --------------------------------------------------------------------------------------------
    private void SetupImages()
    {
      _Images.Images.Add("Access2007", Resources.Access2007);
      _Images.Images.Add("Box", Resources.Box);
      _Images.Images.Add("Button", Resources.Button);
      _Images.Images.Add("ButtonGroup", Resources.ButtonGroup);
      _Images.Images.Add("CheckBox", Resources.Checkbox);
      _Images.Images.Add("ComboBox", Resources.ComboBox);
      _Images.Images.Add("ContextualTab", Resources.ContextualTab);
      _Images.Images.Add("Control", Resources.Control);
      _Images.Images.Add("DialogBoxLauncher", Resources.DialogBoxLauncher);
      _Images.Images.Add("DropDown", Resources.DropDown);
      _Images.Images.Add("DynamicMenu", Resources.DynamicMenu);
      _Images.Images.Add("EditBox", Resources.EditBox);
      _Images.Images.Add("Excel2007", Resources.Excel2007);
      _Images.Images.Add("Gallery", Resources.Gallery);
      _Images.Images.Add("Group", Resources.Group);
      _Images.Images.Add("Label", Resources.Label);
      _Images.Images.Add("Menu", Resources.Menu);
      _Images.Images.Add("NotInTheRibbon", Resources.NotInTheRibbon);
      _Images.Images.Add("MenuSeparator", Resources.MenuSeparator);
      _Images.Images.Add("OutLook2007", Resources.Outlook2007);
      _Images.Images.Add("OfficeApp", Resources.OfficeApp);
      _Images.Images.Add("OfficeMenu", Resources.OfficeMenu);
      _Images.Images.Add("PowerPoint2007", Resources.PowerPoint2007);
      _Images.Images.Add("Qat", Resources.Qat);
      _Images.Images.Add("Ribbon", Resources.Ribbon);
      _Images.Images.Add("RibbonTab", Resources.RibbonTab);
      _Images.Images.Add("Separator", Resources.Separator);
      _Images.Images.Add("SplitButton", Resources.SplitButton);
      _Images.Images.Add("TabSet", Resources.Tabset);
      _Images.Images.Add("ToggleButton", Resources.ToggleButton);
      _Images.Images.Add("Word2007", Resources.Word2007);
    }

    #endregion

    #region INvaigationSupport implementation

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Gest the images used by navigation services.
    /// </summary>
    /// <returns>List of images</returns>
    // --------------------------------------------------------------------------------------------
    public ImageList GetNavigationImages()
    {
      return _Tree.ImageList;  
    }

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Gets the navigation path for the specified tree node.
    /// </summary>
    /// <param name="node">Node to obtain the path for.</param>
    /// <returns>
    /// Navigation path. Returns null, if the node is the root in the tree.
    /// </returns>
    // --------------------------------------------------------------------------------------------
    public TreeNode GetPath(TreeNode node)
    {
      if (node.Parent == null) return null;
      TreeNode upperPath = null;
      if (!(node is OfficeAppTreeNode))
      {
        // --- This node has a parent up the path
        upperPath = GetPath(node.Parent);
      }

      // --- Clone the node and add to the parent
      TreeNode nodeClone = new TreeNode(node.Text);
      nodeClone.ImageKey = node.ImageKey;
      nodeClone.SelectedImageKey = node.SelectedImageKey;
      nodeClone.Tag = node;
      if (upperPath == null)
      {
        return nodeClone;
      }

      // --- Find the end node of the path
      TreeNode lastNode = upperPath;
      while (lastNode.Nodes.Count >0)
      {
        lastNode = lastNode.Nodes[0];
      }
      lastNode.Nodes.Add(nodeClone);
      return upperPath;
    }

    // --------------------------------------------------------------------------------------------
    /// <summary>
    /// Navigates to the specified tree node.
    /// </summary>
    /// <param name="node">Tree node to navigate to.</param>
    // --------------------------------------------------------------------------------------------
    public void NavigateTo(TreeNode node)
    {
      node.EnsureVisible();
      _Tree.SelectedNode = node;
    }

    #endregion
  }
}
